package pl.edu.mimuw.irs.rcp.controller.editor.requirements;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EventObject;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.gef.ui.properties.UndoablePropertySheetEntry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.PropertySheetPage;

import pl.edu.mimuw.irs.core.model.design.net.IRSRequirement;
import pl.edu.mimuw.irs.core.model.design.resource.Roles;
import pl.edu.mimuw.irs.rcp.util.MessageCode;
import pl.edu.mimuw.irs.rcp.util.UITexts;

public class RequirementsEditor extends EditorPart implements PropertyChangeListener {
	
	public static final String ID = "pl.edu.mimuw.irs.editor.requirements";
	public static final String COMMAND_ID = "pl.edu.mimuw.irs.command.editrequirements";

	// *** Attributes
	
	private IRSRequirement requirement;
	private Roles rolesMap;
	private Label lblName;
	private Text txtName;
	private Label lblTimeUnits;
	private Spinner spnTimeUnits;
	private Label lblRoles;
	private Button btnOk;
	private Button btnCancel;
	private RequirementsTreeWrapper treRequirements;
	public IRSRequirement getRequirement() {
		return requirement;
	}
	public void setRequirement(IRSRequirement requirements) {
		this.requirement = requirements;
	}
	public Roles getRolesMap() {
		if (rolesMap == null) rolesMap = new Roles();
		return rolesMap;
	}
	public void setRolesMap(Roles rolesMap) {
		this.rolesMap = rolesMap;
	}
	
	private EditDomain editDomain;
	private boolean dirty;
	private PropertySheetPage propertySheetPage;
	private CommandStackListener commandStackListener = new CommandStackListener() {
		public void commandStackChanged(EventObject event) {
			setDirty(getCommandStack().isDirty());
		}
	};
	public EditDomain getEditDomain() {
		if (editDomain == null) editDomain = new DefaultEditDomain(this);
		return editDomain;
	}
	public void setDirty(boolean dirty) {
		if (this.dirty != dirty) {
			this.dirty = dirty;
			firePropertyChange(IEditorPart.PROP_DIRTY);
		}
	}
	@Override
	public boolean isDirty() {
		return dirty;
	}
	protected PropertySheetPage getPropertySheetPage() {
		if (propertySheetPage == null) {
			propertySheetPage = new PropertySheetPage();
			propertySheetPage.setRootEntry(
					new UndoablePropertySheetEntry(getCommandStack()));
		}
		return propertySheetPage;
	}
	public CommandStack getCommandStack() {
		return getEditDomain().getCommandStack();
	}
	protected CommandStackListener getCommandStackListener() {
		return commandStackListener;
	}
	
	
	// *** Methods

	@Override
	public void doSave(IProgressMonitor monitor) {
		// XXX : container editor save

	}

	@Override
	public void doSaveAs() {
		// XXX : Auto-generated method stub

	}

	@Override
	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		setSite(site);
		setInput(input);
		setRequirement(((RequirementsEditorInput) input).getRequirement());
		setRolesMap(((RequirementsEditorInput) input).getRolesMap());
		setPartName(getRequirement().getId());
		getRequirement().getRequirements().addPropertyChangeListener(this);

		getCommandStack().addCommandStackListener(getCommandStackListener());
	}

	@Override
	public void dispose() {
		super.dispose();
		getRequirement().getRequirements().removePropertyChangeListener(this);
		
		getCommandStack().removeCommandStackListener(getCommandStackListener());
	}

	@Override
	public boolean isSaveAsAllowed() {
		// XXX save allowed
		return true;
	}

	@Override
	public void createPartControl(Composite parent) {
		GridData gridData;
		Composite composite =  new Composite(parent, SWT.NULL);

	    // create the desired layout for this wizard page
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 2;
		composite.setLayout(gridLayout);
		
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.BEGINNING;	
		
		lblName = new Label(composite, SWT.NONE);
		lblName.setText(UITexts.get(MessageCode.REQUIREMENTS_EDITOR_NAME));				
		txtName = new Text(composite, SWT.BORDER);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		//gridData.horizontalSpan = ncol - 1;
		txtName.setLayoutData(gridData);
		txtName.setText(getRequirement().getId());
		
		lblTimeUnits = new Label(composite, SWT.NONE);
		lblTimeUnits.setText(UITexts.get(MessageCode.REQUIREMENTS_EDITOR_TIME_UNITS));				
		spnTimeUnits = new Spinner(composite, SWT.BORDER);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		//gridData.horizontalSpan = ncol - 1;
		spnTimeUnits.setLayoutData(gridData);
		spnTimeUnits.setMinimum(0);
		spnTimeUnits.setMaximum(10000);
		spnTimeUnits.setSelection(getRequirement().getTimeUnits());
		spnTimeUnits.setIncrement(1);
		spnTimeUnits.setPageIncrement(100);

		gridData = new GridData();
		lblRoles = new Label(composite, SWT.NONE);
		lblRoles.setText(UITexts.get(MessageCode.REQUIREMENTS_EDITOR_CONTENTS));
		gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
		treRequirements = new RequirementsTreeWrapper(composite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL, 
				getRequirement().getRequirements(), getEditDomain());
		treRequirements.setLayoutData(gridData);
		//tblRoles.redraw();
		//setErrorMessage(null);
		//setMessage(UITexts.get(MessageCode.PROJECT_WIZARD_PROJECT_INTRO));
		
		btnOk = new Button(composite, SWT.NONE);
		btnOk.setText(UITexts.get(MessageCode.BUTTON_OK));
		btnOk.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				performOk();
				super.widgetSelected(e);
			}
		});
		btnCancel = new Button(composite, SWT.NONE);
		btnCancel.setText(UITexts.get(MessageCode.BUTTON_CANCEL));
		btnCancel.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				performCancel();
				super.widgetSelected(e);
			}
		});
		
		getSite().setSelectionProvider(treRequirements.getTreeViewer());
		
	}
	
	protected void performOk() {
		/*try {
			getRequirement().setId(txtName.getText());
		} catch (InternalException e) {
			Logger.handle(MessageCode.REQUIREMENTS_EDITOR_NAME, e, txtName.getText()); // XXX
		}*/
		getRequirement().setTimeUnits(spnTimeUnits.getSelection());
		getSite().getPage().closeEditor(this, false);
	}

	protected void performCancel() {
		getSite().getPage().closeEditor(this, false);
	}
	
	private void refresh() {
		txtName.setText(getRequirement().getId());
		treRequirements.redrawTree();
	}

	@Override
	public void setFocus() {
	}
	
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		refresh();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Object getAdapter(Class adapter) {
		if (adapter == CommandStack.class)
			return getCommandStack();
		else if (adapter == EditDomain.class)
			return getEditDomain();
		else if (adapter == IPropertySheetPage.class)
			return getPropertySheetPage();
		// the super implementation handles the rest
		return super.getAdapter(adapter);
	}

}
